package com.free.front.bf.product;

import com.deco.domain.vo.product.AccodeQueryLogVo;
import com.deco.domain.vo.product.PqmsHistoryVo;
import com.deco.service.product.AccodeQueryLogService;
import com.deco.service.product.PqmsHistoryService;
import com.deco.service.sys.CmsAdvService;
import com.deco.service.sys.CmsAdvTypeService;
import com.free.exception.SystemException;
import com.free.ext.httpclient.HttpClientUtil;
import com.free.ext.httpclient.HttpConfig;
import com.free.ext.httpclient.HttpHeader;
import com.free.ext.httpclient.utils.SSLs;
import com.free.ext.logger.FreeLogger;
import com.free.ext.logger.FreeLoggerFactory;
import com.free.front.util.Mu;
import com.free.utils.DateUtils;
import com.free.utils.JsonUtils;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.xml.namespace.QName;
import java.io.*;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

//import com.free.ext.httpclient.HttpClientUtil;
//import com.free.ext.httpclient.HttpConfig;
//import com.free.ext.httpclient.HttpHeader;

/**
 * <p>
 * 功能概述:
 * </p>
 * <p>
 * 功能详述:
 * </p>
 */
@Component
public class ProductSecurityBf {
    /*========================================================================*
     *                         Public Fields (公共属性)
     *========================================================================*/

    /*========================================================================*
     *                         Private Fields (私有属性)
     *========================================================================*/
    // banner
    private static final String BANNER = "prodBanner";

    private static final FreeLogger LOG = FreeLoggerFactory.getLogger(ProductSecurityBf.class);
    
	@Autowired
	private CmsAdvTypeService cmsAdvTypeService;
    
	@Autowired
	private CmsAdvService cmsAdvService;

	@Autowired
	private AccodeQueryLogService accodeQueryLogService;

	@Autowired
	private PqmsHistoryService pqmsHistoryService;

	@Value(value = "${pqms.day.maxcount}")
	private Integer pqmsDayMaxCount;

	@Autowired
	private JksBf jksBf;

	public Map<String, Object> getCnnResult(String ip,String code, String channel) {
		Map<String, Object> res = new HashMap<>();

	       try {    	   
	     	 Map<String, Object> item = doresult(code, channel, ip);
			   LOG.info("安全码查询OLD正常结束:");
	     	 if(item.containsKey("result")){
				 if(!item.get("result").toString().equals("true")){
				 	LOG.info("PQMS查询1:");
					 item = doHttpResult(code,ip,"5");
					 //item = doHttpResult2(code,ip,"5");
				 }
			 }else{
				 LOG.info("PQMS查询2:");
				 item = doHttpResult(code,ip,"5");
			 }
	         AccodeQueryLogVo accodeQueryLogVo = new AccodeQueryLogVo();
	         for (String k : item.keySet())  {  
	        	 //System.out.println(k);
	        	 //System.out.println(item.get(k).toString());
	        	 res.put(k, item.get(k).toString());
	             if("firstQueryDate".equals(k) && !"".equals(item.get(k).toString())){
	            	 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");
	  	             accodeQueryLogVo.setResultFirstquerydate(sdf.parse(item.get(k).toString()));
	             }
	             
	             if("queryCount".equals(k)){
	            	 accodeQueryLogVo.setResultQuerycount(Integer.parseInt(item.get(k).toString()));	
	             }
	             
	             if("result".equals(k)){
	            	 accodeQueryLogVo.setResultValue(item.get(k).toString()=="true" ? true : false);	
	             }
	             
	             if("systemState".equals(k)){
	            	 accodeQueryLogVo.setResultCode(item.get(k).toString());	
	             }
         }  
         accodeQueryLogVo.setQueryIp(ip);	
         accodeQueryLogVo.setQueryAccode(code);	
         accodeQueryLogVo.setQueryChannel(channel);
         accodeQueryLogVo.setQueryTime(new Timestamp(System.currentTimeMillis()));	
         accodeQueryLogVo.setQueryLanguage("zh-cn");
         accodeQueryLogService.save(accodeQueryLogVo);         
	     }
	     catch(Exception e){ 
	     	 LOG.info("添加查询真伪码出错：" + e.getCause().getClass() + "," + e.getCause().getMessage());
	     	 e.printStackTrace();
	     }
	     return res;
	}

	private Map<String,Object> doHttpResult(String code, String ip, String queryType) throws SystemException {
		Map outRes = new HashMap();
		if(!isValid(ip)){
			outRes.put("result","false");
			outRes.put("systemState","101");
		}
		Map<String,Object> params = new HashMap<>();
		params.put("securityCode",code);
		params.put("ip",ip);
		params.put("queryType",queryType);
		params.put("queryAddress","南京");
		String reqStr = JsonUtils.searlize(params);
		String res = jksBf.sendPost("https://b2bapi.saic-gm.com/pqms/PQMS_FW_QUERY",reqStr);
		LOG.info("安全码查询结果pqms:{},{}", code, res);
		addHistory(ip);
		Map resMap = JsonUtils.unsearlize(res,Map.class);
		outRes.put("code",code);
		if(resMap!=null){
			if(resMap.get("status").toString().equals("S")){
				outRes.put("result","true");

				Map detailMap = (Map)resMap.get("details");
				if(detailMap == null){
					outRes.put("queryCount","1");
					outRes.put("systemState","10020401");
				}else{
					outRes.put("queryCount",detailMap.get("digitalQueryQty").toString());
					if(detailMap.containsKey("firstQueryTime")){
						Date queryTime = DateUtils.convert2Date(detailMap.get("firstQueryTime").toString(), DateUtils.FormatEnum.yyyy_MM_dd_HH_mm_ss);
					 	outRes.put("firstQueryDate",DateUtils.convert2String(queryTime, DateUtils.FormatEnum.yyyyMMDDHHMMSS_CN));
					}
					if(detailMap.get("digitalQueryQty").toString().equals("1")){
						outRes.put("systemState","10020401");
					}else{
						outRes.put("systemState","10020402");
					}
				}
			}else{
				outRes.put("result","false");
				outRes.put("systemState","101");
			}
		}
		LOG.info("安全码查询最终结果pqms:{},{}", code, outRes.toString());
		return outRes;
	}

	 private Map<String, Object> doresult(String acCode, String channel, String ip){
	    	Map<String, Object> result = new HashMap<String, Object>();
	    	try{
	    		result.put("code", acCode);
	    		result.put("isWechat", "20".equals(channel) ? true : false);
	        	Map<String, String> item = check(acCode, channel, ip);	
	    		result.put("result", item.get("result"));
		        String reply = item.get("reply");


		        if(result.get("result") == "true"){	
			        Document doc = DocumentHelper.parseText(reply);		        
			        Map map = Dom2Map(doc);
			        Map itemMap=(Map)map.get("item");       
			        if(Mu.isNotBlank(itemMap.get("firstQueryDate").toString())){
			        	String d = itemMap.get("firstQueryDate").toString();
			            d = d.replaceFirst("/", "年");
			            d = d.replaceFirst("/", "月");
			            d = d.replaceFirst(" ", "日");
			            d = d.replaceFirst(":", "时");
			            d = d.replaceFirst(":", "分");
			            d = d+"秒";
			            result.put("firstQueryDate", d);  
			        }
			        String c = itemMap.get("queryCount").toString();
			        if(Mu.isNotBlank(c)){
			          result.put("queryCount", Mu.ckInt(c));
			        }
			        result.put("product", itemMap.get("product").toString());
			        if(StringUtils.isEmpty(result.get("product").toString())){
						item.put("result", "false");
					}
		        }
		       for (String k : item.keySet())
		       {  
		    	  result.put(k, item.get(k));
		       }  
		       return result;
		    }
		    catch(Exception e){
		    	LOG.info("安全吗查询OLD：" + e.getCause().getClass() + "," + e.getCause().getMessage());
		    	e.printStackTrace();
		    	return null;
		    }
	   }

	   private boolean isValid(String ip) {
			PqmsHistoryVo historyVo = new PqmsHistoryVo();
			historyVo.setIp(ip);
			historyVo.setCdate(new Date());
			return pqmsHistoryService.count(historyVo)<= pqmsDayMaxCount;
	   }

	   private void addHistory(String ip) {
			PqmsHistoryVo historyVo = new PqmsHistoryVo();
			historyVo.setIp(ip);
			historyVo.setCdate(new Date());
			pqmsHistoryService.add(historyVo);
	   }

	  public static Map<String, Object> Dom2Map(Document doc){
	        Map<String, Object> map = new HashMap<String, Object>();
	        if(doc == null)
	            return map;
	        Element root = doc.getRootElement();
	        for (Iterator iterator = root.elementIterator(); iterator.hasNext();) {
	            Element e = (Element) iterator.next();
	            //System.out.println(e.getName());
	            List list = e.elements();
	            if(list.size() > 0){
	                map.put(e.getName(), Dom2Map(e));
	            }else
	                map.put(e.getName(), e.getText());
	        }
	        return map;
	    }
	 
	   public static Map Dom2Map(Element e){
	        Map    map = new HashMap();
	        List list = e.elements();
	        if(list.size() > 0){
	            for (int i = 0;i < list.size(); i++) {
	                Element iter = (Element) list.get(i);
	                List mapList = new ArrayList();
	                
	                if(iter.elements().size() > 0){
	                    Map m = Dom2Map(iter);
	                    if(map.get(iter.getName()) != null){
	                        Object obj = map.get(iter.getName());
	                        if(!obj.getClass().getName().equals("java.util.ArrayList")){
	                            mapList = new ArrayList();
	                            mapList.add(obj);
	                            mapList.add(m);
	                        }
	                        if(obj.getClass().getName().equals("java.util.ArrayList")){
	                            mapList = (List) obj;
	                            mapList.add(m);
	                        }
	                        map.put(iter.getName(), mapList);
	                    }else
	                        map.put(iter.getName(), m);
	                }
	                else{
	                    if(map.get(iter.getName()) != null){
	                        Object obj = map.get(iter.getName());
	                        if(!obj.getClass().getName().equals("java.util.ArrayList")){
	                            mapList = new ArrayList();
	                            mapList.add(obj);
	                            mapList.add(iter.getText());
	                        }
	                        if(obj.getClass().getName().equals("java.util.ArrayList")){
	                            mapList = (List) obj;
	                            mapList.add(iter.getText());
	                        }
	                        map.put(iter.getName(), mapList);
	                    }else
	                        map.put(iter.getName(), iter.getText());
	                }
	            }
	        }else
	            map.put(e.getName(), e.getText());
	        return map;
	    }
	  
	private Map<String, String> check(String acCode, String channel, String ip) {
		try{
    		Date date = new Date();
        	SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        	String str = sdf1.format(date);
        	//LOG.info("调用WebService开始时间："+str+", code:"+ acCode +"\r\n");
        	    		
		    Properties p = new Properties();
		    try{
		    	InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("setting-web.properties");
		        p.load(inputStream);
		    } catch (IOException e1){
		    	e1.printStackTrace();
		    	//LOG.info("调用WebService出错，读取参数：" + e1.getCause().getClass() + "," + e1.getCause().getMessage());
		    }
    		
		    String endpoint = p.getProperty("ccnout.checkAcWeb");
		    String namespace = p.getProperty("ccnout.checkAcNamespace");
		    String method = p.getProperty("ccnout.checkAcMethod");
		    String username = p.getProperty("ccnout.checkAcUser");
		    String password = p.getProperty("ccnout.checkAcPassword");
		    
		    Service service = new Service();
		    Call call = (Call)service.createCall();
		    call.setTargetEndpointAddress(new java.net.URL(endpoint));

		    QName reply = new QName(namespace,"reply");
	        QName systemState = new QName(namespace,"systemState");
       
		    call.setOperationName(new QName(namespace, method));
		    call.addParameter(new QName(namespace,"userID"),org.apache.axis.encoding.XMLType.XSD_STRING,javax.xml.rpc.ParameterMode.IN);   
		    call.addParameter(new QName(namespace,"userPwd"),org.apache.axis.encoding.XMLType.XSD_STRING,javax.xml.rpc.ParameterMode.IN); 
		    call.addParameter(new QName(namespace,"ip"),org.apache.axis.encoding.XMLType.XSD_STRING,javax.xml.rpc.ParameterMode.IN); 
		    call.addParameter(new QName(namespace,"acCode"),org.apache.axis.encoding.XMLType.XSD_STRING,javax.xml.rpc.ParameterMode.IN); 
		    call.addParameter(new QName(namespace,"language"),org.apache.axis.encoding.XMLType.XSD_STRING,javax.xml.rpc.ParameterMode.IN);
		    call.addParameter(new QName(namespace,"channel"),org.apache.axis.encoding.XMLType.XSD_STRING,javax.xml.rpc.ParameterMode.IN);		   
		    call.addParameter(reply ,org.apache.axis.encoding.XMLType.XSD_STRING,javax.xml.rpc.ParameterMode.OUT);
		    call.addParameter(systemState ,org.apache.axis.encoding.XMLType.XSD_STRING,javax.xml.rpc.ParameterMode.OUT);
		    
		    call.setReturnType(org.apache.axis.encoding.XMLType.XSD_BOOLEAN);
		    call.setUseSOAPAction(true);
	        call.setSOAPActionURI(namespace+method);
	        
	        //String ip = Mu.getIP(request);
	        Date sendDate = new Date();
        	String sendStartDate = sdf1.format(sendDate);
        	
        	//Log.info("调用WebService发送时间："+sendStartDate+", code:"+ acCode +"\r\n");	       	
	        Boolean retVal = (Boolean) call.invoke(new Object[] { username, password , ip, acCode, "zh-cn", channel});  
	        
	        Date recevieDate = new Date();
        	String sendEndDate = sdf1.format(recevieDate);
        	long sendinterval = (recevieDate.getTime() - sendDate.getTime());
        	//LOG.info("调用WebService接收时间："+sendEndDate+", code:"+ acCode +"，耗时："+sendinterval+"毫秒\r\n");	
        	
        	
	        Map<String, String> result = new HashMap<String, String>();
	        result.put("result", retVal.toString());
	        Map item = call.getOutputParams();	        
			LOG.info("安全码查询结果OLD:{},{}", acCode, item.toString());
	        if(item.containsKey(reply)){       	 
	        	result.put("reply", item.get((Object)reply).toString());
				LOG.info("安全码查询结果OLD:reply:{}", result.get("reply"));
	        }else{
	        	result.put("result","false");
			}
	        if(item.containsKey(systemState)){       	 
	        	result.put("systemState", item.get((Object)systemState).toString());
	        }		        
	        
	        Date date1 = new Date();
        	String str1 = sdf1.format(date1);
        	long suminterval = (date1.getTime() - date.getTime());
        	//LOG.info("调用WebService结束时间："+str1+", code:"+ acCode +",总共耗时:"+suminterval+"毫秒\r\n");	
        	
	        return result;
	    }
		catch (Exception e) {
			LOG.info("安全码查询结果OLD：" + e.getCause().getClass() + "," + e.getCause().getMessage());
			e.printStackTrace();
			return null;
	    }
	}


	public static void main(String[] args) throws SystemException, IOException {
//		ProductSecurityBf bf = new ProductSecurityBf();
//		try {
//			bf.doHttpResult("8481200590628218","183.212.172.194","5");
//		} catch (SystemException e) {
//			e.printStackTrace();
//		}
//		Map<String,String> params = new HashMap<>();
//		params.put("tes","1");
//		System.out.println(params.toString());

//		String time = "2019-01-14 14:41:53.0";
//		Date dt = DateUtils.convert2Date(time, DateUtils.FormatEnum.yyyy_MM_dd_HH_mm_ss);
//		System.out.println(DateUtils.convert2String(dt, DateUtils.FormatEnum.yyyyMMDDHHMMSS_CN));

	}


}
